package org.example.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.example.common.utils.RequestUtils;
import org.example.common.utils.IpLocationUtils;
import org.example.common.utils.SaTokenUtils;
import org.example.common.utils.TenantContext;
import org.example.entity.Company;
import org.example.entity.EmployeeProfile;
import org.example.entity.Role;
import org.example.entity.User;
import org.example.mapper.CompanyMapper;
import org.example.mapper.RoleMapper;
import org.example.mapper.UserRoleCompanyRelationMapper;
import org.example.mapper.UserRolePlatformRelationMapper;
import org.example.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 认证服务实现类
 */
@Service
@Slf4j
public class AuthServiceImpl implements AuthService {
    
    @Autowired
    private SmsService smsService;
    
    @Autowired
    private UserService userService;
    
    @Autowired
    private PermissionService permissionService;
    
    @Autowired
    private RoleService roleService;
    
    @Autowired
    private SaTokenUtils saTokenUtils;
    
    @Autowired
    private UserRolePlatformRelationMapper userRolePlatformRelationMapper;
    
    @Autowired
    private UserRoleCompanyRelationMapper userRoleCompanyRelationMapper;
    
    @Autowired
    private CompanyMapper companyMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private LoginLogService loginLogService;
    
    @Autowired
    private EmployeeProfileService employeeProfileService;
    
    @Override
    public Map<String, Object> platformLogin(String phone, String verificationCode) {
        // 验证验证码
        boolean isValid = smsService.verifyCode(phone, verificationCode, "平台端");
        if (!isValid) {
            throw new RuntimeException("验证码错误或已过期");
        }
        
        // 从数据库查询用户信息（指定平台端类型）
        User user = userService.getByPhoneAndUserType(phone, "平台端");
        if (user == null) {
            throw new RuntimeException("用户不存在或无权限");
        }
        
        // 角色名称：仅以平台关联表为准，取第一条
        String roleName = null;
        try {
            java.util.List<Long> roleIds = userRolePlatformRelationMapper.getRoleIdsByUserId(user.getId());
            if (roleIds != null && !roleIds.isEmpty()) {
                Long roleId = roleIds.get(0);
                Role role = roleService.getPlatformRoleById(roleId);
                if (role != null) {
                    roleName = role.getRoleName();
                }
            }
        } catch (Exception ignore) { }
        
        // 构建用户信息
        Map<String, Object> userInfo = new HashMap<>();
        userInfo.put("id", user.getId());
        userInfo.put("username", user.getUsername());
        userInfo.put("realName", user.getRealName());
        userInfo.put("phone", user.getPhone());
        userInfo.put("userType", "平台端");
        userInfo.put("isPlatformAdmin", user.getIsPlatformAdmin());
        // 附加角色名（平台端从平台关联取）
        if (roleName != null) {
            userInfo.put("roleName", roleName);
        }
        
        // 使用 Sa-Token 登录
        saTokenUtils.login(user.getId(), "平台端");
        String token = saTokenUtils.getTokenValue();
        // 记录登录成功日志（平台端不关联公司）
        try {
            String sessionId = saTokenUtils.getSessionId();
            String ip = RequestUtils.getClientIp();
            String ua = RequestUtils.getUserAgent();
            String location = IpLocationUtils.getLocationByIp(ip);
            loginLogService.recordLoginSuccess(user.getId(), "平台端", null, ip, location, ua, sessionId);
        } catch (Exception ignore) {}
        
        // 获取用户权限：仅以平台关联为准
        List<String> permissions = permissionService.getPlatformPermissionsByUserId(user.getId());
        
        Map<String, String> permissionCatalog = ((PermissionServiceImpl)permissionService).getPermissionMapByApp("platform");
        // 仅返回用户拥有权限的名称映射，避免把全部权限字典下发
        Map<String, String> permissionMap = new HashMap<>();
        if (permissions != null && !permissions.isEmpty() && permissionCatalog != null) {
            for (String code : permissions) {
                String name = permissionCatalog.get(code);
                if (name != null) {
                    permissionMap.put(code, name);
                }
            }
        }
        
        // 构建登录结果
        Map<String, Object> result = new HashMap<>();
        result.put("token", token);
        result.put("userInfo", userInfo);
        result.put("permissions", permissions);
        result.put("permissionMap", permissionMap);
        // Sa-Token 自动管理过期时间，这里设置一个默认值
        result.put("expiresAt", System.currentTimeMillis() + 30 * 24 * 60 * 60 * 1000L); // 30天
        result.put("expiresIn", 30 * 24 * 60 * 60 * 1000L); // 30天
        
        return result;
    }
    
    @Override
    public Map<String, Object> enterpriseLogin(String phone, String verificationCode, String companyId) {
        // 验证验证码
        boolean isValid = smsService.verifyCode(phone, verificationCode, "enterprise");
        if (!isValid) {
            // 记录登录失败日志
            try {
                String ip = org.example.common.utils.RequestUtils.getClientIp();
                String ua = org.example.common.utils.RequestUtils.getUserAgent();
                loginLogService.recordLoginFailure(null, "企业端", null, ip, null, ua, "验证码错误或已过期");
            } catch (Exception ignore) {}
            throw new RuntimeException("验证码错误或已过期");
        }
        
        // 从数据库查询用户信息（指定企业端类型）
        User user = userService.getByPhoneAndUserType(phone, "企业端");
        if (user == null) {
            throw new RuntimeException("用户不存在或无权限");
        }
        
        // 多租户处理：如果指定了companyId，验证用户是否有权限访问该租户
        Long targetCompanyId = null;
        if (companyId != null && !companyId.trim().isEmpty()) {
            try {
                targetCompanyId = Long.valueOf(companyId);
                // 验证用户是否有权限访问该租户
                if (!userService.hasAccessToCompany(user.getId(), targetCompanyId)) {
                    throw new RuntimeException("用户无权访问指定的企业租户");
                }
            } catch (NumberFormatException e) {
                throw new RuntimeException("租户ID格式错误");
            }
        } else {
            // 如果没有指定租户，自动获取用户的第一个企业作为默认值
            try {
                List<Long> userCompanyIds = userRoleCompanyRelationMapper.getCompanyIdsByUserId(user.getId());
                if (userCompanyIds != null && !userCompanyIds.isEmpty()) {
                    targetCompanyId = userCompanyIds.get(0); // 取第一个企业作为默认
                    log.info("用户 {} 自动设置默认企业ID: {}", user.getId(), targetCompanyId);
                } else {
                    // 如果用户角色关联表中没有企业，说明用户未关联任何企业
                    targetCompanyId = null;
                }
            } catch (Exception e) {
                log.warn("获取用户企业列表失败: {}", e.getMessage());
                targetCompanyId = null;
            }
            
            if (targetCompanyId == null) {
                throw new RuntimeException("用户未关联任何企业租户，请先联系管理员分配企业权限");
            }
        }
        
        // 构建用户基础信息（从users表获取基础信息）
        Map<String, Object> userInfo = new HashMap<>();
        userInfo.put("id", user.getId());
        userInfo.put("phone", user.getPhone());
        userInfo.put("userType", "企业端");
        userInfo.put("currentCompanyId", targetCompanyId);
        
        // 获取公司名称
        try {
            Company company = companyMapper.selectById(targetCompanyId);
            if (company != null) {
                userInfo.put("currentCompanyName", company.getCompanyName());
            }
        } catch (Exception ignore) {}
        
        // 从员工档案表获取企业相关信息
        try {
            EmployeeProfile profile = employeeProfileService.getByUserIdAndCompanyId(user.getId(), targetCompanyId);
            if (profile != null) {
                userInfo.put("realName", profile.getRealName());
                userInfo.put("employeeCode", profile.getEmployeeCode());
                userInfo.put("department", profile.getDepartment());
                userInfo.put("position", profile.getPosition());
            }
        } catch (Exception ignore) {}
        
        // 角色信息通过单独查询获取
        try {
            java.util.List<Long> entRoleIds = userRoleCompanyRelationMapper.getRoleIdsByUserIdAndCompanyId(user.getId(), targetCompanyId);
            if (entRoleIds != null && !entRoleIds.isEmpty()) {
                Long roleId = entRoleIds.get(0);
                Role role = roleMapper.selectById(roleId);
                if (role != null) {
                    userInfo.put("roleName", role.getRoleName());
                }
            }
        } catch (Exception ignore) {}
        
        // 使用 Sa-Token 登录（多端隔离）
        String token = saTokenUtils.loginWithCompanyId(user.getId(), "企业端", targetCompanyId);
        // 记录登录成功日志
        try {
            String sessionId = saTokenUtils.getSessionId();
            String ip = org.example.common.utils.RequestUtils.getClientIp();
            String ua = org.example.common.utils.RequestUtils.getUserAgent();
            String location = org.example.common.utils.IpLocationUtils.getLocationByIp(ip);
            loginLogService.recordLoginSuccess(user.getId(), "企业端", targetCompanyId, ip, location, ua, sessionId);
        } catch (Exception ignore) {}
        
        // 获取用户权限：基于当前租户
        List<String> permissions = permissionService.getEnterprisePermissionsByUserId(user.getId(), targetCompanyId);
        
        Map<String, String> permissionCatalog = ((PermissionServiceImpl)permissionService).getPermissionMapByApp("enterprise");
        Map<String, String> permissionMap = new HashMap<>();
        if (permissions != null && !permissions.isEmpty() && permissionCatalog != null) {
            for (String code : permissions) {
                String name = permissionCatalog.get(code);
                if (name != null) {
                    permissionMap.put(code, name);
                }
            }
        }
        
        // 构建登录结果
        Map<String, Object> result = new HashMap<>();
        result.put("token", token);
        result.put("userInfo", userInfo);
        result.put("permissions", permissions);
        result.put("permissionMap", permissionMap);
        result.put("currentCompany", targetCompanyId);
        // Sa-Token 自动管理过期时间，这里设置一个默认值
        result.put("expiresAt", System.currentTimeMillis() + 30 * 24 * 60 * 60 * 1000L); // 30天
        result.put("expiresIn", 30 * 24 * 60 * 60 * 1000L); // 30天
        
        return result;
    }
    
    @Override
    public Map<String, Object> userLogin(String phone, String verificationCode, String companyId) {
        // 验证验证码
        boolean isValid = smsService.verifyCode(phone, verificationCode, "user");
        if (!isValid) {
            try {
                String ip = org.example.common.utils.RequestUtils.getClientIp();
                String ua = org.example.common.utils.RequestUtils.getUserAgent();
                loginLogService.recordLoginFailure(null, "企业端", null, ip, null, ua, "验证码错误或已过期");
            } catch (Exception ignore) {}
            throw new RuntimeException("验证码错误或已过期");
        }
        
        // 从数据库查询用户信息（指定用户端类型）
        User user = userService.getByPhoneAndUserType(phone, "企业端");
        if (user == null) {
            throw new RuntimeException("用户不存在或无权限");
        }
        
        // 多租户处理：如果指定了companyId，验证用户是否有权限访问该租户
        Long targetCompanyId = null;
        if (companyId != null && !companyId.trim().isEmpty()) {
            try {
                targetCompanyId = Long.valueOf(companyId);
                // 验证用户是否有权限访问该租户
                if (!userService.hasAccessToCompany(user.getId(), targetCompanyId)) {
                    throw new RuntimeException("用户无权访问指定的企业租户");
                }
            } catch (NumberFormatException e) {
                throw new RuntimeException("租户ID格式错误");
            }
        } else {
            // 如果没有指定租户，自动获取用户的第一个企业作为默认值
            try {
                List<Long> userCompanyIds = userRoleCompanyRelationMapper.getCompanyIdsByUserId(user.getId());
                if (userCompanyIds != null && !userCompanyIds.isEmpty()) {
                    targetCompanyId = userCompanyIds.get(0); // 取第一个企业作为默认
                    log.info("用户 {} 自动设置默认企业ID: {}", user.getId(), targetCompanyId);
                } else {
                    // 如果用户角色关联表中没有企业，说明用户未关联任何企业
                    targetCompanyId = null;
                }
            } catch (Exception e) {
                log.warn("获取用户企业列表失败: {}", e.getMessage());
                targetCompanyId = null;
            }
            
            if (targetCompanyId == null) {
                throw new RuntimeException("用户未关联任何企业租户，请先联系管理员分配企业权限");
            }
        }
        
        // 构建用户基础信息（从users表获取基础信息）
        Map<String, Object> userInfo = new HashMap<>();
        userInfo.put("id", user.getId());
        userInfo.put("phone", user.getPhone());
        userInfo.put("userType", "企业用户端");
        userInfo.put("currentCompanyId", targetCompanyId);
        
        // 从员工档案表获取企业相关信息
        try {
            EmployeeProfile profile = employeeProfileService.getByUserIdAndCompanyId(user.getId(), targetCompanyId);
            if (profile != null) {
                userInfo.put("realName", profile.getRealName());
                userInfo.put("employeeCode", profile.getEmployeeCode());
                userInfo.put("department", profile.getDepartment());
                userInfo.put("position", profile.getPosition());
            }
        } catch (Exception ignore) {}
        
        // 角色信息通过单独查询获取
        try {
            java.util.List<Long> userRoleIds = userRoleCompanyRelationMapper.getRoleIdsByUserIdAndCompanyId(user.getId(), targetCompanyId);
            if (userRoleIds != null && !userRoleIds.isEmpty()) {
                Long roleId = userRoleIds.get(0);
                Role role = roleMapper.selectById(roleId);
                if (role != null) {
                    userInfo.put("roleName", role.getRoleName());
                }
            }
        } catch (Exception ignore) {}
        
        // 使用 Sa-Token 登录（多端隔离）
        String token = saTokenUtils.loginWithCompanyId(user.getId(), "企业端", targetCompanyId);
        try {
            String sessionId = saTokenUtils.getSessionId();
            String ip = saTokenUtils.getClientIp();
            String ua = saTokenUtils.getUserAgent();
            String location = org.example.common.utils.IpLocationUtils.getLocationByIp(ip);
            loginLogService.recordLoginSuccess(user.getId(), "企业端", targetCompanyId, ip, location, ua, sessionId);
        } catch (Exception ignore) {}
        
        // 获取用户权限：基于当前租户
        List<String> permissions = permissionService.getUserPermissionsByUserId(user.getId(), targetCompanyId);
        
        Map<String, String> permissionCatalog = ((PermissionServiceImpl)permissionService).getPermissionMapByApp("user");
        Map<String, String> permissionMap = new HashMap<>();
        if (permissions != null && !permissions.isEmpty() && permissionCatalog != null) {
            for (String code : permissions) {
                String name = permissionCatalog.get(code);
                if (name != null) {
                    permissionMap.put(code, name);
                }
            }
        }
        
        // 构建登录结果
        Map<String, Object> result = new HashMap<>();
        result.put("token", token);
        result.put("userInfo", userInfo);
        result.put("permissions", permissions);
        result.put("permissionMap", permissionMap);
        result.put("currentCompany", targetCompanyId);
        // Sa-Token 自动管理过期时间，这里设置一个默认值
        result.put("expiresAt", System.currentTimeMillis() + 30 * 24 * 60 * 60 * 1000L); // 30天
        result.put("expiresIn", 30 * 24 * 60 * 60 * 1000L); // 30天
        
        return result;
    }
    
    @Override
    public Map<String, Object> verifyToken(String token) {
        try {
            // 验证Token
            if (!saTokenUtils.isLogin()) {
                throw new RuntimeException("Token已过期或无效");
            }
            
            // 构建用户信息
            Map<String, Object> userInfo = new HashMap<>();
            userInfo.put("id", saTokenUtils.getCurrentUserId());
            userInfo.put("phone", saTokenUtils.getCurrentUserPhone());
            userInfo.put("userType", saTokenUtils.getCurrentUserType());
            // 从租户上下文获取companyId（多端隔离）
            userInfo.put("companyId", TenantContext.getCurrentCompanyId());
            
            return userInfo;
        } catch (Exception e) {
            throw new RuntimeException("Token验证失败");
        }
    }
    
    @Override
    public void logout(String token) {
        try {
            Long userId = saTokenUtils.getCurrentUserId();
            String sessionId = saTokenUtils.getSessionId();
            if (userId != null && sessionId != null) {
                loginLogService.recordLogout(userId, sessionId);
            }
        } catch (Exception ignore) {}
        log.info("用户退出登录: {}", token);
    }
    
    @Override
    public Map<String, Object> switchTenant(String token, Long tenantId) {
        if (token == null || !saTokenUtils.isLogin()) {
            throw new RuntimeException("Token已过期或无效");
        }
        Long userId = saTokenUtils.getCurrentUserId();
        String userType = saTokenUtils.getCurrentUserType();

        if (tenantId == null) {
            throw new RuntimeException("租户ID不能为空");
        }
        // 校验访问权限
        if (!userService.hasAccessToCompany(userId, tenantId)) {
            throw new RuntimeException("用户无权访问指定的企业租户");
        }

        User user = userService.getById(userId);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }

        // 方案四：重新签发token，包含新的companyId，实现完全的多端隔离
        // 生成包含新companyId的token
        String newToken = saTokenUtils.loginWithCompanyId(userId, userType, tenantId);

        // 不同端分别处理权限与roleName
        if ("企业端".equals(userType)) {
            // userInfo
            Map<String, Object> userInfo = new HashMap<>();
            userInfo.put("id", user.getId());
            userInfo.put("phone", user.getPhone());
            userInfo.put("userType", userType);
            userInfo.put("currentCompanyId", tenantId);
            
            // 从员工档案表获取企业相关信息
            try {
                EmployeeProfile profile = employeeProfileService.getByUserIdAndCompanyId(userId, tenantId);
                if (profile != null) {
                    userInfo.put("realName", profile.getRealName());
                    userInfo.put("username", profile.getUsername());
                    userInfo.put("employeeCode", profile.getEmployeeCode());
                    userInfo.put("department", profile.getDepartment());
                    userInfo.put("position", profile.getPosition());
                } else {
                    // 如果档案不存在，使用用户基础信息
                    userInfo.put("realName", user.getRealName());
                    userInfo.put("username", user.getUsername());
                }
            } catch (Exception ignore) {
                // 异常时使用用户基础信息
                userInfo.put("realName", user.getRealName());
                userInfo.put("username", user.getUsername());
            }
            try {
                java.util.List<Long> entRoleIds = userRoleCompanyRelationMapper.getRoleIdsByUserIdAndCompanyId(userId, tenantId);
                if (entRoleIds != null && !entRoleIds.isEmpty()) {
                    Role role = roleMapper.selectById(entRoleIds.get(0));
                    if (role != null) {
                        userInfo.put("roleName", role.getRoleName());
                    }
                }
            } catch (Exception ignore) {}

            // permissions
            List<String> permissions = permissionService.getEnterprisePermissionsByUserId(userId, tenantId);
            Map<String, String> permissionCatalog = ((PermissionServiceImpl)permissionService).getPermissionMapByApp("enterprise");
            Map<String, String> permissionMap = new HashMap<>();
            if (permissions != null && !permissions.isEmpty() && permissionCatalog != null) {
                for (String code : permissions) {
                    String name = permissionCatalog.get(code);
                    if (name != null) {
                        permissionMap.put(code, name);
                    }
                }
            }

            Map<String, Object> result = new HashMap<>();
            // 方案四：返回新token，实现完全的多端隔离
            result.put("token", newToken);  // 新token
            result.put("userInfo", userInfo);
            result.put("permissions", permissions);
            result.put("permissionMap", permissionMap);
            result.put("currentCompany", tenantId);
            result.put("message", "租户切换成功，新token已生成");
            return result;
        }

        if ("用户端".equals(userType)) {
            Map<String, Object> userInfo = new HashMap<>();
            userInfo.put("id", user.getId());
            userInfo.put("phone", user.getPhone());
            userInfo.put("userType", userType);
            userInfo.put("currentCompanyId", tenantId);
            
            // 从员工档案表获取企业相关信息
            try {
                EmployeeProfile profile = employeeProfileService.getByUserIdAndCompanyId(userId, tenantId);
                if (profile != null) {
                    userInfo.put("realName", profile.getRealName());
                    userInfo.put("username", profile.getUsername());
                    userInfo.put("employeeCode", profile.getEmployeeCode());
                    userInfo.put("department", profile.getDepartment());
                    userInfo.put("position", profile.getPosition());
                } else {
                    // 如果档案不存在，使用用户基础信息
                    userInfo.put("realName", user.getRealName());
                    userInfo.put("username", user.getUsername());
                }
            } catch (Exception ignore) {
                // 异常时使用用户基础信息
                userInfo.put("realName", user.getRealName());
                userInfo.put("username", user.getUsername());
            }
            try {
                java.util.List<Long> userRoleIds = userRoleCompanyRelationMapper.getRoleIdsByUserIdAndCompanyId(userId, tenantId);
                if (userRoleIds != null && !userRoleIds.isEmpty()) {
                    Role role = roleMapper.selectById(userRoleIds.get(0));
                    if (role != null) {
                        userInfo.put("roleName", role.getRoleName());
                    }
                }
            } catch (Exception ignore) {}

            List<String> permissions = permissionService.getUserPermissionsByUserId(userId, tenantId);
            Map<String, String> permissionCatalog = ((PermissionServiceImpl)permissionService).getPermissionMapByApp("user");
            Map<String, String> permissionMap = new HashMap<>();
            if (permissions != null && !permissions.isEmpty() && permissionCatalog != null) {
                for (String code : permissions) {
                    String name = permissionCatalog.get(code);
                    if (name != null) {
                        permissionMap.put(code, name);
                    }
                }
            }

            Map<String, Object> result = new HashMap<>();
            // 方案四：返回新token，实现完全的多端隔离
            result.put("token", newToken);  // 新token
            result.put("userInfo", userInfo);
            result.put("permissions", permissions);
            result.put("permissionMap", permissionMap);
            result.put("currentCompany", tenantId);
            result.put("message", "租户切换成功，新token已生成");
            return result;
        }

        // 平台端不支持
        throw new UnsupportedOperationException("平台端不支持租户切换");
    }
}
